package cc.eddic.examinationsystem.web;

import cc.eddic.examinationsystem.core.BaseController;
import cc.eddic.examinationsystem.domain.Exam;
import cc.eddic.examinationsystem.dto.DemoCheckBoxModel;
import cc.eddic.examinationsystem.dto.DemoModel;
import cc.eddic.examinationsystem.dto.DemoUploadModel;
import cc.eddic.examinationsystem.repository.ExamRepository;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.IOException;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.stream.Collectors;

@Slf4j
@Controller
@RequestMapping("/demo")
public class DemoController extends BaseController {

    private DemoUploadModel uploadModel;

    public DemoController(ExamRepository examRepository) {
        this.examRepository = examRepository;
    }

    @GetMapping("/list")
    public String listForm(Model model) {
        model.addAttribute("dt", LocalDateTime.now());
        model.addAttribute("examList", examRepository.findAll().stream().map(DemoModel::from).collect(Collectors.toList()));
        return "demo-list";
    }

    @GetMapping("/add")
    public String addForm(Model model) {
        model.addAttribute("demoModel", DemoModel.builder().build());
        return "demo-add-edit";
    }

    @GetMapping("/{id}/edit")
    public String editForm(@PathVariable("id") Long id, Model model) {
        model.addAttribute("demoModel", examRepository.findById(id).map(DemoModel::from).orElse(DemoModel.builder().build()));
        return "demo-add-edit";
    }

    @PostMapping(value = "/{id}/delete")
    public String delete(@PathVariable("id") Long id, Model model) {
        if (log.isDebugEnabled()) log.debug("id = {}", id);
        examRepository.deleteById(id);
        return "redirect:/demo/list";
    }


    @PostMapping(value = "/save", params = "save")
    public String save(@ModelAttribute @Valid DemoModel demoModel, BindingResult bindingResult, Model model) {
        if (log.isDebugEnabled()) log.debug("examModel = {}", demoModel);

        if (bindingResult.hasErrors()) {
            if (log.isDebugEnabled()) log.debug("bindingResult = {}", bindingResult);
            model.addAttribute("examModel", demoModel);
            return "demo-add-edit";
        }

        Exam exam;
        if (demoModel.getId() == null) {
            if (log.isDebugEnabled()) log.debug("add");

            exam = new Exam(demoModel.getName(), demoModel.getExamAt(), demoModel.getTimeLimit(), demoModel.getTotalScore());
        } else {
            if (log.isDebugEnabled())
                log.debug("edit : id = {}, version = {}", demoModel.getId(), demoModel.getVersion());

            val optionalExam = examRepository.findByIdAndVersion(demoModel.getId(), demoModel.getVersion());
            if (!optionalExam.isPresent()) {
                if (log.isDebugEnabled()) log.debug("not found {}", demoModel.getId());

                bindingResult.reject("ERROR", String.format("找不到 Id = %d 且 Version = %d 的数据", demoModel.getId(), demoModel.getVersion()));
                return "demo-add-edit";
            }

            exam = optionalExam.get();
            exam.setName(demoModel.getName());
            exam.setExamAt(demoModel.getExamAt());
            exam.setTimeLimit(demoModel.getTimeLimit());
            exam.setTotalScore(demoModel.getTotalScore());
        }
        examRepository.save(exam);

        return "redirect:/demo/list";
    }


    @GetMapping("/checkbox")
    public String checkBoxForm(Model model) {
        model.addAttribute("cityModel", new DemoCheckBoxModel());
        return "demo-checkbox";
    }

    @PostMapping("/checkbox/save")
    public String checkBoxSave(@ModelAttribute DemoCheckBoxModel checkBoxModel, Model model) {
        if (log.isDebugEnabled()) log.debug("checkBoxModel = {}", checkBoxModel);

        return "redirect:/demo/checkbox";
    }

    @GetMapping("/upload")
    public String uploadForm(Model model) {
        model.addAttribute("uploadModel", new DemoUploadModel());
        return "demo-upload";
    }

    @PostMapping("/upload/save")
    public String upload(@ModelAttribute DemoUploadModel uploadModel, Model model) {
        if (log.isDebugEnabled()) {
            log.debug("description = {}", uploadModel.getDescription());
            log.debug("{} {}", uploadModel.getFile().getOriginalFilename(), uploadModel.getFile().getSize());
        }

        val p = Paths.get(uploadPath, FORMATTER.format(LocalDateTime.now()) + "_" + uploadModel.getFile().getOriginalFilename());
        try {
            uploadModel.getFile().transferTo(p);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }

        return "redirect:/demo/upload";
    }


    private final ExamRepository examRepository;

    @Value("${eddic.exam.upload.path}")
    private String uploadPath;

    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss_SSS");
}
